module AboutYou
  module SDK
    module Model
      ###
      # This class represents a variant model
      ###
      class Variant
        include AbstractModel
        # instance of AboutYou::SDK::Factory::DefaultModelFactory
        attr_accessor :factory
        # instance of AboutYou::SDK::Model::Product
        attr_accessor :product
        # Integer id
        attr_accessor :id
        # Array of AboutYou::SDK::Model::Image
        attr_accessor :images
        # instance of AboutYou::SDK::Model::Image
        attr_accessor :selected_image
        # Integer about number id
        attr_accessor :about_number
        # Array of AboutYou::SDK::Model::FacetGroup
        attr_accessor :facet_groups
        # String ean
        attr_accessor :ean
        # Boolean is variant default for product or not
        attr_accessor :is_default
        # Integer price
        attr_accessor :price
        # Integer old price
        attr_accessor :old_price
        # Integer retail price
        attr_accessor :retail_price
        # additional information
        attr_accessor :additional_info
        # integer quantity
        attr_accessor :quantity
        # Array of Integer facet_ids
        attr_accessor :facet_ids
        # Integer first active data
        attr_accessor :first_active_date
        # integer first Sale data
        attr_accessor :first_sale_date
        # Integer creation date
        attr_accessor :created_date
        # Integer update Date
        attr_accessor :updated_date
        # String color
        attr_accessor :color
        # Integer length
        attr_accessor :length
        # string season_code
        attr_accessor :season_code

        ###
        # This method is used for creating an instance of this class by a json_object.
        #
        # * *Args*    :
        #   - +json_object+ -> the json_object received from the api
        #   - +factory+ -> instance of AboutYou::SDK::Factory::DefaultModelFactory
        #   - +product+ -> Product of this variant
        #
        # * *Fails* :
        #   - if json_object has no id 
        #
        # * *Returns* :
        #   - Instance of AboutYou::SDK::Model::Variant
        ###
        def self.create_from_json(json_object, factory, product)
          fail 'MalformedJsonException' unless json_object['id']

          variant                   = new
          variant.factory           = factory
          variant.product           = product

          variant.images            = variant.parse_images(json_object['images'])
          # free memory
          json_object['images']     = nil

          variant.id                = json_object['id']
          variant.about_number      = (json_object['about_number']) ? json_object['about_number'] : nil
          variant.ean               = (json_object['ean']) ? json_object['ean'] : nil
          variant.is_default        = (json_object['default']) ? json_object['default'] : nil
          variant.price             = (json_object['price']) ? json_object['price'] : nil
          variant.old_price         = (json_object['old_price']) ? json_object['old_price'] : nil
          variant.retail_price      = (json_object['retail_price']) ? json_object['retail_price'] : nil
          variant.additional_info   = (json_object['additional_info']) ? json_object['additional_info'] : nil
          variant.quantity          = (json_object['quantity']) ? json_object['quantity'] : 0
          variant.first_active_date = (json_object['first_active_date']) ? json_object['first_active_date'] : nil
          variant.first_sale_date   = (json_object['first_sale_date']) ? json_object['first_sale_date'] : nil
          variant.created_date      = (json_object['created_date']) ? json_object['created_date'] : nil
          variant.updated_date      = (json_object['updated_date']) ? json_object['updated_date'] : nil

          variant.facet_ids         = variant.parse_facet_ids(json_object)
          variant.facet_groups      = variant.generate_facet_group_set(json_object)
          variant.color             = variant.facet_group(AboutYou::SDK::Model::Facet::FACET_COLOR)
          variant.length            = variant.facet_group(AboutYou::SDK::Model::Facet::FACET_LENGTH)
          variant.season_code       = variant.facet_group(AboutYou::SDK::Model::Facet::FACET_SEASON_CODE)

          variant
        end

        ###
        # This method is used for parsing images
        #
        # * *Args*    :
        #   - +image_json+ -> the image json_object received from the api
        #
        # * *Returns* :
        #   - [] / Array of instances of AboutYou::SDK::Model::Image
        ###
        def parse_images(image_json)
          image_array = []
          image_json.each do |image|
            image_array.push(factory.create_image(image))
          end if image_json

          image_array
        end

        ###
        # This method searches for an image by a certain hash
        #
        # * *Args*    :
        #   - +hash+ -> the hash used for searching
        #
        # * *Returns* :
        #   - nil / instance of AboutYou::SDK::Model::Image
        ###
        def image_by_hash(hash)
          images.each do |image|
            return image if image.hash == hash
          end

          nil
        end

        ###
        # You can select an image with this method by a certain hash
        #
        # * *Args*    :
        #   - +hash+ -> the hash used for selecting [optional]
        #
        # * *Returns* :
        #   - Boolean determining whether the selection was successful or not
        ###
        def select_image(hash = nil)
          if hash
            self.selected_image = image_by_hash(hash)
            true
          else
            self.selected_image = nil
            false
          end
        end

        ###
        # Getter for selected / default image
        #
        # * *Returns* :
        #   - nil / AboutYou::SDK::Model::Image
        ###
        def image
          if selected_image
            return selected_image
          elsif images[0]
            return images[0]
          end

          nil
        end

        ###
        # This method parses the facet ids of a certain json_object
        #
        # * *Args*    :
        #   - +json_object+ -> The json_object received from the api
        #
        # * *Returns* :
        #   - {} / Hash containing pairs of group_id => attribute_ids
        ###
        def parse_facet_ids(json_object)
          ids = {}

          json_object['attributes'].each do |group, attribute_ids|
            group_id = group[11..group.length] # rm prefix 'attributs_'
            ids[Integer(group_id)] = attribute_ids
          end unless json_object['attributes'].empty?

          ids
        end

        ###
        # This method generated a facet group set for a certain json_object
        #
        # * *Args*    :
        #   - +json_object+ -> The json_object received from the api
        ###
        def generate_facet_group_set(json_object)
          ids = parse_facet_ids(json_object)
          self.facet_groups = AboutYou::SDK::Model::FacetGroupSet.new(ids)
        end

        ###
        # This method searches by a certain facet group id
        #
        # * *Args*    :
        #   - +group_id+ -> The group_id used for searching
        #
        # * *Returns* :
        #   - nil / instance of AboutYou::SDK::Model::FacetGroup
        ###
        def facet_group(group_id)
          facet_groups.group(group_id)
        end

        ###
        # Getter for the size facet group
        #
        # * *Returns* :
        #   - instance of AboutYou::SDK::Model::FacetGroup
        ###
        def size
          # @todo: Instance level caching
          group_id = size_group_id
          facet_group(group_id) unless group_id.empty?
        end

        ###
        # This method is used for getting the size group id
        #
        # * *Returns* :
        #   - nil / group_id
        ###
        def size_group_id
          keys = {}
          groups = facet_groups.groups
          size_run = facet_group(AboutYou::SDK::Model::Facet::FACET_SIZE_RUN)

          groups.each do |group|
            keys[group.name] = group.group_id
          end if groups.is_a?(Array)

          size_run.facets.each do |facet|
            group_name = facet.value
            return keys[group_name] if keys.key?(group_name)
          end unless size_run.empty?

          return keys['size'] if keys.key?('size')

          return keys['size_run'] if keys.key?('size_run')

          nil
        end

        ###
        # Getter for the quantity per pack
        #
        # * *Returns* :
        #   - Integer quantity
        ###
        def quantity_per_pack
          facet_group = facet_group(
            AboutYou::SDK::Model::Facet::FACET_QUANTITY_PER_PACK
          )
          return 1 unless facet_group

          facets = facet_group.facets
          return 1 unless facets

          facets[0].value
        end
      end
    end
  end
end
